<?php
/**
 * Each engineer has a duty to keep the code elegant
 * Created by wolffy.
 * Author @wolffy<13750088090@sina.cn>
 * Date: 2018/8/9
 * Time: 17:31
 */
namespace App\Services;

use App\Handlers\ApiResponse;
use App\Repositories\SmsLogRepository;

class CloudspSMS
{
    use ApiResponse;
    use RedisService;
    protected $errorCode = [
        9001 => '签名格式不正确',
        9002 => '参数未赋值',
        9003 => '手机号码格式不正确',
        9006 => '用户accessKey不正确',
        9007 => 'IP白名单限制',
        9009 => '短信内容参数不正确',
        9010 => '用户短信余额不足',
        9011 => '用户帐户异常',
        9012 => '日期时间格式不正确',
        9013 => '不合法的语音验证码，4~8位的数字',
        9014 => '超出了最大手机号数量',
        9015 => '不支持的国家短信',
        9016 => '无效的签名或者签名ID',
        9017 => '无效的模板ID',
        9018 => '单个变量限制为1-20个字',
        9019 => '内容不可以为空',
    ];
    protected $apiUrl;
    protected $accessKey;
    protected $secret;
    protected $sign;
    protected $templateIdCode;
    protected $templateIdCreateOrder;
    protected $templateIdFailOrder;
    protected $templateIdSuccessOrder;
    protected $isOpen;
    protected $smsLogRepository;

    public function __construct(SmsLogRepository $smsLogRepository)
    {
        $this->apiUrl = config('cloudspsms.api_url');
        $this->accesskey = config('cloudspsms.accesskey');
        $this->secret = config('cloudspsms.secret');
        $this->sign = config('cloudspsms.sign');
        $this->templateIdCode = config('cloudspsms.templateIdCode');
        $this->templateIdCreateOrder = config('cloudspsms.templateIdCreateOrder');
        $this->templateIdFailOrder = config('cloudspsms.templateIdFailOrder');
        $this->templateIdSuccessOrder = config('cloudspsms.templateIdSuccessOrder');
        $this->isOpen = config('cloudspsms.is_open');
        $this->smsLogRepository = $smsLogRepository;

    }

    /**
     * 选择模板发送短信
     * @param $mobile
     * @param $content
     * @param $templateType
     * @return array
     */
    public function sendSMS($mobile, $content, $templateType, $scene)
    {
        $redisKey = '';
        $redisKeyLimit = 0;
        if ('register' == $templateType) {
            $templateId = $this->templateIdCode;
            $redisKey = $this->redisKeyCodeUserRegister() . $mobile;
            $redisKeyLimit = $this->redisKeyCodeUserRegisterLimit() . $mobile;
        }
        if ('forgetPassword' == $templateType) {
            $templateId = $this->templateIdCode;
            $redisKey = $this->redisKeyCodeUserForgetPassword() . $mobile;
            $redisKeyLimit = $this->redisKeyCodeUserForgetPasswordLimit() . $mobile;
        }
        if ('forgetPayPassword' == $templateType) {
            $templateId = $this->templateIdCode;
            $redisKey = $this->redisKeyCodeUserForgetPayPassword() . $mobile;
            $redisKeyLimit = $this->redisKeyCodeUserForgetPayPasswordLimit() . $mobile;
        }
        if ('truenameAuth' == $templateType) {
            $templateId = $this->templateIdCode;
            $redisKey = $this->redisKeyCodeUserTrueNameAuth() . $mobile;
            $redisKeyLimit = $this->redisKeyCodeUserTrueNameAuthLimit() . $mobile;
        }
        if ('bindBankCard' == $templateType) {
            $templateId = $this->templateIdCode;
            $redisKey = $this->redisKeyCodeUserBindBankCard() . $mobile;
            $redisKeyLimit = $this->redisKeyCodeUserBindBankCardLimit() . $mobile;
        }
        if ('bindCreditCard' == $templateType) {
            $templateId = $this->templateIdCode;
            $redisKey = $this->redisKeyCodeUserBindCreditCard() . $mobile;
            $redisKeyLimit = $this->redisKeyCodeUserBindCreditCardLimit() . $mobile;
        }
        if ('creditCardHandle' == $templateType) {
            $templateId = $this->templateIdCode;
            $redisKey = $this->redisKeyCodeCreditCardHandle() . $mobile;
            $redisKeyLimit = $this->redisKeyCodeCreditCardHandleLimit() . $mobile;
        }
        $isSendCode = $this->limitSend($content, $redisKey, $redisKeyLimit);
        if (!$isSendCode) {
            return $this->responseJson(10109);
        }
        if (!$this->isOpen) {
            $text = '调试短信验证码:' . $isSendCode;
            $this->saveSmsLog($mobile, 0, $text, $scene, '');
            return $this->responseJson(0, [], false, $text, $text);
        }
        $sendParam = $this->sendParam($templateId, $mobile, $isSendCode);
        $client = new \GuzzleHttp\Client();
        $response = $client->request('post', $this->apiUrl, ['form_params' => $sendParam]);
        $json = $response->getBody()->getContents();
        //"{"code":"0","msg":"SUCCESS","smUuid":"17029_1_0_13750088090_1_F2jDdLr_1"}"
        $result = json_decode($json, true);
        if (0 != $result['code']) {
            $this->saveSmsLog($mobile, 0, $isSendCode, $scene, $json);
            return $this->responseJson(400, [], false, $result['msg'], '');
        } else {
            $this->saveSmsLog($mobile, 1, $isSendCode, $scene, $json);
            return $this->responseJson(0, [], false, $result['msg'], '短信发送成功');
        }
    }

    /**
     * 通知短信
     * @param $mobile
     * @param $content
     * @param $templateType
     * @param $scene 业务场景
     */
    public function sendSMSNotify($mobile, $content, $templateType, $scene)
    {
        if (!$this->isOpen) {
            return true;
        }
        $templateId = 0;
        if ('createOrder' == $templateType) {
            $templateId = $this->templateIdCreateOrder;
        }
        if ('successOrder' == $templateType) {
            $templateId = $this->templateIdSuccessOrder;
        }
        if ('failOrder' == $templateType) {
            $templateId = $this->templateIdFailOrder;
        }
        $sendParam = $this->sendParam($templateId, $mobile, $content);
        $client = new \GuzzleHttp\Client();
        $response = $client->request('post', $this->apiUrl, ['form_params' => $sendParam]);
        $json = $response->getBody()->getContents();
        //"{"code":"0","msg":"SUCCESS","smUuid":"17029_1_0_13750088090_1_F2jDdLr_1"}"
        $result = json_decode($json, true);
        if (0 != $result['code']) {
            $this->saveSmsLog($mobile, 0, $content, $scene, $json);
            return false;
        } else {
            $this->saveSmsLog($mobile, 1, $content, $scene, $json);
            return false;
        }
    }

    /**
     * 发送参数
     * @param $templateId
     * @param $mobile
     * @param $content
     * @return array
     */
    protected function sendParam($templateId, $mobile, $content)
    {
        return [
            'accesskey' => $this->accesskey,
            'secret' => $this->secret,
            'sign' => $this->sign,
            'templateId' => $templateId,
            'mobile' => $mobile,
            'content' => $content,
        ];
    }

    /**
     * 保存发送短信日志
     * @param $mobile
     * @param $randStr
     * @param $status
     * @param $msg
     * @param $scene
     * @param string $errorMsg
     */
    public function saveSmsLog($mobile, $status, $msg, $scene, $errorMsg = "")
    {
        $data = [
            'mobile' => $mobile,
            'status' => $status,
            'msg' => $msg,
            'scene' => $scene,
            'error_msg' => $errorMsg,
            'send_time' => time(),
            'send_ip' => request()->ip(),
        ];
        $this->smsLogRepository->create($data);
    }
    
    /**
     * 限制发送短信
     */
    public function limitSend($text, $redisKey, $redisKeyLimit)
    {
        if ($this->redis()->exists($redisKey) && $this->redis()->exists($redisKeyLimit)) {
            $redisValue = $this->redis()->get($redisKey);
            $limit = $this->redis()->get($redisKeyLimit);
            if (!empty($redisValue) && $limit < 3) {
                $limitTTl = $this->redis()->ttl($redisKeyLimit);
                $this->redis()->setex($redisKeyLimit, $limitTTl, $limit + 1);
                return $redisValue;
            } else {
                return false;
            }
        } else {
            $this->redis()->setex($redisKey, 300, $text);
            $this->redis()->setex($redisKeyLimit, 300, 1);
            return $text;
        }
    }
}